Basic
import React from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(
<h1>Hello, World!</h1>,
document.querySelector('#root')
);
render some JSX to the <div id="root"></div> in your HTML
JSX
HTML you can directly write HTML in JSX and assign it to a variable
如果有大段HTML,用圆括号扩起来
JS Expressions use any Javascript expression in a curly braces
{ 2 + 2 },{ user.name },{ showMenu() }epxression can even be used in attributesJSX use camelCase property in HTML
class => classNametabindex => tabIndexJSX will be compiled as object
Render
ReactDOM.render(element,DOM);
React 的 Element 是不可变的,每次UI的变化都需要重新调用 ReactDOM.render() 方法
function tick () {
const element = <h3>It is { new Date().toLocaleTimeString() }</h3>
ReactDOM.render(
element,
document.querySelector('#root')
);
}
setInterval(tick, 1000);
在实际操作中,只会调用一次Render 方法,并且通过Stateful Component 去改变UI
Components
**Component 接受 props 参数并返回相应的 UI **
主要有两种相同的定义模式,分别如下:
Functional
function Welcome (props) {
return <h1>Welcome {props.name}</h1>
}
// HTML
<Welcome name='Ethan'>
ES6 Class
class Welcome extends React.Component {
render() {
return <h1>Welcome, {this.props.name}</h1>
}
}
// HTML
<Welcome name='Ethan'></Welcome>
Props
React 约定不能在组建内部修改传入的 props
Render
在 component 的 Render 方法中,可以添加逻辑代码甚至变量:
class LoginControl extends React.Components {
constructor(){};
render () {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutBtn onClick={this.loggedOut}></LogoutBtn>;
} else {
button = <LogoutBtn onClick={this.loggedIn}></LogoutBtn>;
}
return (
<div>
{button}
</div>
)
}
}
Inline & operator
curly brace and operator (&&, ?😃 can also make condition
class Mailbox extends React.Component {
constructor(props){super(props)};
return (
<div>
{
props.messageNum > 0 &&
<h1>You have {props.messageNum} unread message</h1>
}
</div>
)
}
ReactDOM.render(
<Mailbox messageNum=3></Mailbox>,
DomElement
);
Render Nothing
if sometimes you want to hide the component, simply set a condition to retrun null
##Status & Lifecycle
status is similar to props, but it’s private and fully controlled by component
but for data not shown in UI, you shouldn’t put it in status.
class Clock extends React.Component {
constructor (props) {
super(props);
this.state = {date: new Date()}
}
componentDidMount () {
this.timerID = setInterval(
() => this.tick(),
100
)
}
componentWillUnmount () {
clearInterval(this.timerID);
}
tick () {
this.setState({
date: new Date()
})
}
render () {
return <h3>It is {this.state.date.toLocaleString()}. </h3>
}
}
- State have to use class mode
- Props have to use the super() 类似于 Parent.call(this),用于继承父类this
- Changing state has to use
this.setState({a: '123'}) - If state based on previous state, use
this.setState((prevState, props)=>({a: prevState.a + 1})) - State can pass down to child component as props
- Data can only flows down, called unidirectiona data flow
Lifecycle Hooks
componentDidMount
componentWillUnmount
Events
React use camelCase event handler rather than lowercase
onclick => onClick
We should not call addEventListener in React, instead, we should provide a listener when the element in initially rendered.
如果要在 event function 中使用 this,需要在constructor 里绑定this
this.eventHandler = this.eventHandler.bind(this)或者使用 ES6 尖头函数自动绑定this,如下例handleClick = () => { this.setState(); }
Lists & Keys
const listItem = [1, 2, 3, 4, 5].map((num) => {
<li>{num}</li>
});
return (<ul>{listItem}</ul>);
but most times we should add keys for whatever list so React can detect the change of the list node.
we use index for keys in the case below (not recommend because slow) but if possible we should use id property of data.
const listItem = [1, 2, 3, 4, 5].map((num, index) => {
<li key={index}>{num}</li>
//<li key={num.id}>{num.number}</li>
//<li key={num.toString()}>{num}</li>
});
return (<ul>{listItem}</ul>);
Keys have to be identical among siblings
Form
similar to Angular & Vue, use state to gather data
class NameForm extends React.Component {
constructor(props) {
super(props);
this.state = {
nameValue: ''
};
}
handleChange = (e) => this.setState({nameValue: e.target.value})
handleSubmit = (e) => {
// do something
e.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
Name: <input type="text"
value={this.state.value}
onChange={this.handleChange}
/>
</form>
)
}
}
State 提升
在有多个 input 互相嵌套的情况下,我们尽量把 state 尽可能的提升到高的组建层,然后通过 props 向下传递数据
Composition
like the slug in Vue, the props.children is specifically used as slug for other component.
function FancyBorder(props) {
return (
<div className={'FancyBorder-' + props.color}>
{props.children}
</div>
)
}
function WelcomeDialog() {
return (
<FancyBorder color='blue'>
<h1>something show in the props.children</h1>
</FancyBorder>
)
}
If multiple holes needed, we can pass the react element as object directly
function FancyBorder(props) {
return (
<div>
<div className="section1">{props.section1}</div>
<div className="section2">{props.section2}</div>
</div>
)
}
function App() {
return (
<FancyBorder
section1={<contracts />}
section2={<Chat />}
)
}